/**
 * Licensed under the Apache License Version 2.0.
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package net.interknit.knitter.cg.view;

import java.util.Collection;

import net.interknit.knitter.cg.layout.CollectionElement;
import net.interknit.knitter.cg.layout.LayoutElement;
import net.interknit.knitter.cg.model.JavaType;
import net.interknit.knitter.cg.util.ReflectionHelper;

/**
 *
 */
public class CollectionTypeView extends JavaTypeView
{
	public CollectionTypeView(JavaType javaType)
	{
		super(javaType);
	}

	@Override
	protected String[] getAdditionalPlaceholders()
	{
		return new String[] {
			"VALUE_GENERIC_1_DECLARATION",
			"STATE_GENERIC_1_INSTANTIATION",
			"STATE_GENERIC_1_DECLARATION",
			"STATE_GENERIC_1_NAME",
			"STATE_GENERIC_1_CONDITIONAL_INSTANTIATION",
			"STATE_GENERIC_1_UNWRAP_CLAUSE",
		};
	}

	@Override
	public LayoutElement getLayoutElement()
	{
		return new CollectionElement(this);
	}

	@Override
	public String STATE_DECLARATION()
	{
		StringBuilder sb = new StringBuilder();

		JavaType javaType = getJavaType();

		assertCondition(javaType.getInspector().isCollectionType(), "STATE_DECLARATION");

		sb.append(ReflectionHelper.getClassName(Collection.class));

		sb.append("<");
		if(! getJavaType().getGenericJavaTypes().isEmpty())
		{
			sb.append(JavaTypeViewFactory.create(getJavaType().getGenericJavaTypes().get(0)).ADAPTER_DECLARATION());
		}
		else if(! getJavaType().getDerivedGenericJavaTypes().isEmpty())
		{
			sb.append(JavaTypeViewFactory.create(getJavaType().getDerivedGenericJavaTypes().get(0)).ADAPTER_DECLARATION());
		}
		sb.append(">");

		return sb.toString();
	}

	@Override
	public String STATE_INSTANTIATION()
	{
		StringBuilder sb = new StringBuilder();

		JavaType javaType = getJavaType().getConcreteJavaType();

		assertCondition(javaType.getInspector().isCollectionType(), "STATE_INSTANTIATION");

		sb.append(ReflectionHelper.getClassName(javaType.getTypeClass()));

		sb.append("<");
		if(! getJavaType().getGenericJavaTypes().isEmpty())
		{
			sb.append(JavaTypeViewFactory.create(getJavaType().getGenericJavaTypes().get(0)).ADAPTER_DECLARATION());
		}
		else if(! getJavaType().getDerivedGenericJavaTypes().isEmpty())
		{
			sb.append(JavaTypeViewFactory.create(getJavaType().getDerivedGenericJavaTypes().get(0)).ADAPTER_DECLARATION());
		}
		sb.append(">");

		return sb.toString();
	}

	public String VALUE_GENERIC_1_DECLARATION()
	{
		JavaType javaType = getJavaType();

		assertCondition(javaType.getInspector().isCollectionType(), "VALUE_GENERIC_1_DECLARATION");

		if(! javaType.getGenericJavaTypes().isEmpty())
		{
			JavaType firstGenericType = javaType.getGenericJavaTypes().get(0);
			return firstGenericType.getJavaTypeDeclaration();
		}
		else
		{
			return "java.lang.Object";
		}
	}

	public String STATE_GENERIC_1_INSTANTIATION()
	{
		JavaType javaType = getJavaType();

		assertCondition(javaType.getInspector().isCollectionType(), "STATE_GENERIC_1_INSTANTIATION");

		JavaType firstGenericType = null;
		if(! javaType.getGenericJavaTypes().isEmpty())
		{
			firstGenericType = javaType.getGenericJavaTypes().get(0);
		}
		else if(! javaType.getDerivedGenericJavaTypes().isEmpty())
		{
			firstGenericType = javaType.getDerivedGenericJavaTypes().get(0);
		}
		return JavaTypeViewFactory.create(firstGenericType).ADAPTER_INSTANTIATION();
	}

	public String STATE_GENERIC_1_DECLARATION()
	{
		JavaType javaType = getJavaType();

		assertCondition(javaType.getInspector().isCollectionType(), "STATE_GENERIC_1_DECLARATION");

		JavaType firstGenericType = null;
		if(! javaType.getGenericJavaTypes().isEmpty())
		{
			firstGenericType = javaType.getGenericJavaTypes().get(0);
		}
		else if(! javaType.getDerivedGenericJavaTypes().isEmpty())
		{
			firstGenericType = javaType.getDerivedGenericJavaTypes().get(0);
		}
		return JavaTypeViewFactory.create(firstGenericType).ADAPTER_DECLARATION();
	}

	public String STATE_GENERIC_1_NAME()
	{
		JavaType javaType = getJavaType();

		assertCondition(javaType.getInspector().isCollectionType(), "STATE_GENERIC_1_NAME");

		JavaType firstGenericType = null;
		if(! javaType.getGenericJavaTypes().isEmpty())
		{
			firstGenericType = javaType.getGenericJavaTypes().get(0);
		}
		else if(! javaType.getDerivedGenericJavaTypes().isEmpty())
		{
			firstGenericType = javaType.getDerivedGenericJavaTypes().get(0);
		}

		String firstGenericTypeName = JavaTypeViewFactory.create(firstGenericType).ADAPTER_NAME();

		if(firstGenericType.getInspector().isPrimitiveType() || firstGenericType.getInspector().isBasicType())
		{
			firstGenericTypeName = ReflectionHelper.getStandardTypeName(firstGenericTypeName);
		}

		return firstGenericTypeName;
	}

	public String STATE_GENERIC_1_CONDITIONAL_INSTANTIATION()
	{
		JavaType javaType = getJavaType();

		assertCondition(javaType.getInspector().isCollectionType(), "STATE_GENERIC_1_CONDITIONAL_INSTANTIATION");

		JavaType firstGenericType = null;
		if(! javaType.getGenericJavaTypes().isEmpty())
		{
			firstGenericType = javaType.getGenericJavaTypes().get(0);
		}
		else if(! javaType.getDerivedGenericJavaTypes().isEmpty())
		{
			firstGenericType = javaType.getDerivedGenericJavaTypes().get(0);
		}

		if(firstGenericType.getInspector().isBasicType() || firstGenericType.getInspector().isJavaTypeIgnored())
		{
			return "v";
		}
		else
		{
			return "new " + JavaTypeViewFactory.create(firstGenericType).ADAPTER_INSTANTIATION() + "(v)";
		}
	}

	public String STATE_GENERIC_1_UNWRAP_CLAUSE()
	{
		JavaType javaType = getJavaType();

		assertCondition(javaType.getInspector().isCollectionType(), "STATE_GENERIC_1_UNWRAP_CLAUSE");

		JavaType firstGenericType = null;
		if(! javaType.getGenericJavaTypes().isEmpty())
		{
			firstGenericType = javaType.getGenericJavaTypes().get(0);
		}
		else if(! javaType.getDerivedGenericJavaTypes().isEmpty())
		{
			firstGenericType = javaType.getDerivedGenericJavaTypes().get(0);
		}
		return JavaTypeViewFactory.create(firstGenericType).UNWRAP_CLAUSE();
	}
}
